package com.smsc.headend.task.engine.handler.impl.firmware;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil;
import com.smsc.headend.common.constant.DeviceModel;
import com.smsc.headend.common.enums.errorcode.TaskHandlerErrorCode;
import com.smsc.headend.module.asset.dmo.ComConfigDMO;
import com.smsc.headend.module.fwu.entity.TemplateFwUpgrade;
import com.smsc.headend.module.protocol.DeviceData;
import com.smsc.headend.module.protocol.ansi.AnsiByteBuffer;
import com.smsc.headend.module.protocol.ansi.AnsiData;
import com.smsc.headend.module.protocol.cosem.bo.CosemData;
import com.smsc.headend.module.task.dto.AtomicTask;
import com.smsc.headend.module.task.dto.AtomicTaskState;
import com.smsc.headend.module.task.dto.Task;
import com.smsc.headend.task.engine.dao.TaskDAO;
import com.smsc.headend.task.engine.exception.UDISTaskHandlerException;
import com.smsc.headend.task.engine.handler.TaskHandler;
import com.smsc.headend.task.engine.service.CosemXmlService;
import com.smsc.headend.task.engine.service.FeignAssetManagementService;
import com.smsc.headend.task.engine.service.firmware.FirmwareService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import java.util.Optional;

/**
 * 确认是否升级成功，
 * 前置升级任务： 类型1:ImageTransfer中的 ImageActivation
 * 类型2:ftp模式 下发后的升级版本确认
 *
 * @author liangli
 * @date 2020/11/10
 */
@Slf4j
public class ReadFirmwareVersionConfirmHandler implements TaskHandler {
    @Autowired
    FeignAssetManagementService assetManagementService;

    @Autowired
    CosemXmlService cosemXmlService;

    @Autowired
    TaskDAO taskDAO;

    @Value("#{T(java.lang.Integer).parseInt('${fwu.step.retryTimes:2}')}")
    Integer firmwareStepsRetry;
    @Autowired
    FirmwareService firmwareService;

    private final static String OCTET_STRING = "OctetString";

    TemplateFwUpgrade.TaskType taskType = TemplateFwUpgrade.TaskType.ImageVerify;

    @Override
    public int handle(Task task, AtomicTask atomicTask, DeviceData deviceData, String actionResult) throws UDISTaskHandlerException {
        if (!(deviceData instanceof CosemData) && !(deviceData instanceof AnsiData)) {
            throw new UDISTaskHandlerException(TaskHandlerErrorCode.DEVICE_DATA_TYPE_NOT_SUPPORT.toString());
        }
        Long fwFileId = Convert.toLong(this.getParameterMap(task, atomicTask).get("fwFileId"));
        Long fwTypeId = Convert.toLong(this.getParameterMap(task, atomicTask).get("fwTypeId"));
        String fwFileTypeVersion = assetManagementService.getFileFirmwareTypeVersion(fwFileId, fwTypeId);
        String versionInDevice;
        if (deviceData instanceof AnsiData) {
            AnsiData ansiData = (AnsiData) deviceData;
            AnsiByteBuffer ansiByteBuffer = ansiData.getAnsiByteBuffer();
            ansiByteBuffer.position(3);
            versionInDevice = String.format("%s.%s", ansiByteBuffer.getUInt8(), ansiByteBuffer.getUInt8());
            log.info("the db fw version is {}, the device fw version is {}", fwFileTypeVersion, versionInDevice);
        } else {
            CosemData cosemData = (CosemData) deviceData;

            Object data = cosemXmlService.getData(cosemData.getType(), cosemData.getValue());
            if (OCTET_STRING.equalsIgnoreCase(cosemData.getType())) {
                try {
                    versionInDevice = HexUtil.decodeHexStr(Convert.toStr(data)).trim();
                } catch (Exception e) {
                    versionInDevice = Convert.toStr(data);
                }
            } else {
                versionInDevice = Convert.toStr(data);
            }
        }
        String rawVersion = versionInDevice;
        ComConfigDMO comConfig = null;
//        if (task.getMeterId() == null) {
//            comConfig = assetService.getComConfigById(task.getComId());
//            if (comConfig != null && DeviceModel.WFCT_960 == comConfig.getModelId()) {
//                //Wisun DCU MasterModule 固件id 11，12 代表同一版本信息中包含两个固件的版本号 ， COM-MASTER(11)是倒数两位， COM-MASTER11(12) 倒数3，4位
//                if (fwFileId == 11L) {
//                    versionInDevice = StrUtil.sub(versionInDevice, versionInDevice.length() - 2, versionInDevice.length());
//                } else if (fwFileId == 12L) {
//                    versionInDevice = StrUtil.sub(versionInDevice, versionInDevice.length() - 4, versionInDevice.length() - 2);
//                }
//            }
//        }

        if (!fwFileTypeVersion.equalsIgnoreCase(versionInDevice)) {
            log.error("confirm failed ,device version {} , firmware version {} ", versionInDevice, fwFileTypeVersion);
            firmwareService.saveFwuReport(task, atomicTask, -1, taskType, StrUtil.format("confirm failed ,device version {} , firmware version {} ", versionInDevice, fwFileTypeVersion), null);
            return -1;
        }
        firmwareService.saveFirmwareVersion(rawVersion, fwTypeId, task, null, comConfig);
        firmwareService.saveFwuReport(task, atomicTask, 1, taskType, "success", null);
        return 1;
    }


    @Override
    public int handleFailure(Task task, AtomicTask atomicTask, String message) {

        log.info("read firmware version confirm error {}, ", message);
        if (firmwareService.isRetryMessageType(message)) {
            AtomicTaskState atomicTaskState = taskDAO.hashGetAtomicTaskState(atomicTask.getAtomicTaskNo());
            if (atomicTaskState.getRetryTimes() >= firmwareStepsRetry) {
                log.error("Image transfer failed retry times over");
                firmwareService.saveFwuReport(task, atomicTask, -1, taskType, StrUtil.format("confirm failed , {}", message), null);
                return -1;
            }
            log.error("Image transfer failed retry times {}", atomicTaskState.getRetryTimes());
            atomicTaskState.setStored(false);
            taskDAO.hashSetAtomicTaskState(atomicTask.getAtomicTaskNo(), task, atomicTaskState.getRetryTimes() + 1, atomicTaskState);
            return 0;
        }
        firmwareService.saveFwuReport(task, atomicTask, -1, taskType, StrUtil.format("confirm failed , {}", message), null);
        log.error("stopFwtask, comId={},meterId={},type={}, messsage={}", task.getComId(), task.getMeterId(), task.getTaskType(), message);
        return -1;
    }
}
